package com.tn.dao;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.Query;
import com.tn.bo.ClientSupplierData;
import com.tn.bo.Company;
import com.tn.service.OfyDataService;


public class CompanyDAO {
	
	public ClientSupplierData findAssociation(String id){
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		return ofy.get(new Key<ClientSupplierData>(ClientSupplierData.class,id));
	}
	
	
	public Company insertCompany(Company company){
		if(StringUtils.isEmpty(company.getCompanyUniqueIdentifier())){
			company.setCompanyUniqueIdentifier(generateCompanyUniqueId("C"));
		}
		if(StringUtils.isEmpty(company.getCompanyId())){
			company.setCompanyId(generateCompanyUniqueId(company.getCompanyName().substring(0,3) + "_"));
		}
		
		Objectify txn = OfyDataService.getInstance().beginOfyTransaction();
		txn.put(company);
		OfyDataService.getInstance().commitOfyTransaction(txn);
		return company;
	}
	
	
	
	public Company findCompanyById(String id){
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		return ofy.get(new Key<Company>(Company.class,id));
	}
	
	public Company findCompanyByCompanyId(String companyId){
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		Query<Company> q = ofy.query(Company.class).filter("companyId", companyId);
		Company c = null;
		for(Company company: q){
			c =  company;
			break;
		}
		
		if(c == null){
			c = this.findCompanyById(companyId);
		}
		return c;
	}
	
	public Company findCompanyByCompanyUniqueId(String companyUniqueId){
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		Query<Company> q = ofy.query(Company.class).filter("companyUniqueIdentifier", companyUniqueId);
		for(Company company: q){
			return company;
		}
		return null;
	}
	
	
	public Company findCompanyBySSN(String ssn){
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		Query<Company> q = ofy.query(Company.class).filter("companySSN", ssn);
		for(Company company: q){
			return company;
		}

		return null;
	}
	
	
	public List<Company>findAllCompanies(){
		ArrayList<Company> retList = new ArrayList<Company>();
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		Query<Company> q = ofy.query(Company.class);
		for(Company header: q){
			retList.add(header);
		}

		return retList;
	}
	
	public List<Company> findCompanyByFilters(Map<String, String> filters){
		ArrayList<Company> retList = new ArrayList<Company>();
		Set<Entry<String,String>> entrySet = filters.entrySet();
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		Query<Company> q = ofy.query(Company.class);
		for(Entry<String, String> entry: entrySet){
			if(StringUtils.isNotEmpty(entry.getValue())){
				q.filter(entry.getKey(), entry.getValue());
			}
		}
		
		for(Company header: q){
			retList.add(header);
		}
		
		return retList;
	}
	
	public void updateCompany(Company c){
		
		Objectify txn = OfyDataService.getInstance().beginOfyTransaction();
		txn.put(c);
		OfyDataService.getInstance().commitOfyTransaction(txn);
	}
	
	public List<Company> findCompanyByNamePattern(String pat){
		List<Company> retList = new ArrayList<Company>();
		Set<Company> filter = new HashSet<Company>();
		String[] literals = StringUtils.split(pat);
		
		//Search with each literal lowercase, uppercase, capitalized.
		if(literals != null && literals.length > 0){
			for(String s: literals){
				//Query 1 - lowercase
				List<Company> list = this.queryByFilterAndStringValue("companyName", StringUtils.lowerCase(s));
				
				//Query 2 - uppercase 
				List<Company> list2 = this.queryByFilterAndStringValue("companyName", StringUtils.upperCase(s));
				
				//Query 2 - capitalize 
				List<Company> list3 = this.queryByFilterAndStringValue("companyName", StringUtils.capitalize(s));
				
				
				if(list != null){
					for(Company c: list){ filter.add(c); }
					
				}
				if(list2 != null){
					for(Company c: list2){ filter.add(c); }
				}
				if(list3 != null){
					for(Company c: list3){ filter.add(c); }
				}
			}
			
		}
		
		retList.addAll(filter);

		return retList;
	}
	
	private List<Company> queryByFilterAndStringValue(String filter, String param){
		List<Company> retList = new ArrayList<Company>();
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		Query<Company> q = ofy.query(Company.class);
				//.filter(filter + " >= ", param)
				//.filter(filter + " < ", param+"\uFFFD"); 
		for(Company company: q){
			retList.add(company);
		}
		return retList;
	}
	
	public List<Company> findSupplierByCompanyId(String companyId){
		Company c = findCompanyByCompanyId(companyId);
		List<Company> retList = new ArrayList<Company>();
		if(c.getSupplierIds() != null){
			for(int i=0;i<c.getSupplierIds().size();i++){
				Company supplier = findCompanyByCompanyId(c.getSupplierIds().get(i));
				retList.add(supplier);
			}
		}
		return retList;
	}
	
	public List<ClientSupplierData> findAssoNByPattern(String pat){
		List<ClientSupplierData> retList = new ArrayList<ClientSupplierData>();
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		Query<ClientSupplierData> q = ofy.query(ClientSupplierData.class).filter("mappingId >=",
				pat).filter("mappingId <", pat+"\uFFFD"); 
		for(ClientSupplierData company: q){
			retList.add(company);
		}

		return retList;
	}
	
	public List<ClientSupplierData> findAssonBySupplier(String suppId){
		List<ClientSupplierData> retList = new ArrayList<ClientSupplierData>();
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		Query<ClientSupplierData> q = ofy.query(ClientSupplierData.class).filter("supplierId",suppId);
		for(ClientSupplierData company: q){
			retList.add(company);
		}

		return retList;
	}
	
	public List<ClientSupplierData> findAssonBySupplierClient(String suppId, String clientId){
		List<ClientSupplierData> retList = new ArrayList<ClientSupplierData>();
		Objectify ofy = OfyDataService.getInstance().getOfyService();
		Query<ClientSupplierData> q = ofy.query(ClientSupplierData.class).filter("supplierId",suppId).filter("clientId", clientId);
		for(ClientSupplierData company: q){
			retList.add(company);
		}

		return retList;
	}
	
	public ClientSupplierData insertAssociation(ClientSupplierData asson){
		Objectify txn = OfyDataService.getInstance().beginOfyTransaction();
		txn.put(asson);
		OfyDataService.getInstance().commitOfyTransaction(txn);
		return asson;
	}
	
	public void updateAssociation(ClientSupplierData asson){
		
		Objectify txn = OfyDataService.getInstance().beginOfyTransaction();
		txn.put(asson);
		OfyDataService.getInstance().commitOfyTransaction(txn);
	}
	
	private String generateCompanyUniqueId(String prefix){
		return prefix + System.currentTimeMillis();
	}

}
